Skip to content

Add Deep Links #10834

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Mar 21, 2025
Merged

Add Deep Links #10834

merged 28 commits into from
Mar 21, 2025

Conversation

freddyaboulton
Copy link
Collaborator

@freddyaboulton freddyaboulton commented Mar 18, 2025

Description

Closes: #2269

Adds gr.DeepLinkButton - a button that snapshots the current state of the app and generates a short link that points to that snapshot. The deep links are of the form <app-url>?deep_link=<short-hash> and are automatically copied to the clipboard for easy sharing.

Under the hood:

  • We store pointers to the serialized values in the StateHolder. This should be a minimal increase in server memory usage since we're already storing all other props in the StateHolder and the serialized value is small since it's serialized.
  • When the deep link button is clicked - the current components are serialized to a file in the cache dir. This is to preserve the state of the app in perpetuity. We can add a "time out" for the deep links and clear these files but I don't think that's necessary.
  • This current server-based approach supports both SSR and non-ssr apps along with multipage.
  • The render decorator is partially supported. If you have a render event that is triggered based on another component's state, then the deep link will capture the trigger component state and the subsequent render output. But subsequent interactions with the rendered components will not be captured. The issue I think is two-fold: rendered components are not added in the config so the app doesn't know where to place them. The render component adds a load event that runs the render event when the page first loads. So even if we captured the rendered components in the config, they would be overwritten by the render load event.
  • The current limitation is that components are not sent to the backend unless they are part of an event (either input or output). This means that if a component is modified but not part of an event, then it's not captured in a deep link. I think that's ok since users want to deeplink interesting generations and if a component is not a part of that then it doesn't matter what the state is.

Sharing Image Gen

image_share

Sharing chatbot

chatbot_share

Sharing Render

render_share

Invalid Share Link UX

inavlid_share

🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is an existing issue for this change. If not, please create an issue before you create this PR, unless the fix is very small.

Not adhering to this guideline will result in the PR being closed.

Testing and Formatting Your Code

  1. PRs will only be merged if tests pass on CI. We recommend at least running the backend tests locally, please set up your Gradio environment locally and run the backed tests: bash scripts/run_backend_tests.sh

  2. Please run these bash scripts to automatically format your code: bash scripts/format_backend.sh, and (if you made any changes to non-Python files) bash scripts/format_frontend.sh

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Mar 18, 2025

🪼 branch checks and previews

Name Status URL
Spaces ready! Spaces preview
Website ready! Website preview
Storybook ready! Storybook preview
🦄 Changes detected! Details

Install Gradio from this PR

pip install https://gradio-pypi-previews.s3.amazonaws.com/25a2f4726cb993970e7353b0ae4d8e4ca02fdc99/gradio-5.22.0-py3-none-any.whl

Install Gradio Python Client from this PR

pip install "gradio-client @ git+https://github.com/gradio-app/gradio@25a2f4726cb993970e7353b0ae4d8e4ca02fdc99#subdirectory=client/python"

Install Gradio JS Client from this PR

npm install https://gradio-npm-previews.s3.amazonaws.com/25a2f4726cb993970e7353b0ae4d8e4ca02fdc99/gradio-client-1.13.1.tgz

Use Lite from this PR

<script type="module" src="https://gradio-lite-previews.s3.amazonaws.com/25a2f4726cb993970e7353b0ae4d8e4ca02fdc99/dist/lite.js""></script>

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Mar 18, 2025

🦄 change detected

This Pull Request includes changes to the following packages.

Package Version
@gradio/client minor
@self/app minor
@self/spa minor
gradio minor
  • Maintainers can select this checkbox to manually select packages to update.

With the following changelog entry.

Add Deep Links

Maintainers or the PR author can modify the PR title to modify this entry.

Something isn't right?

  • Maintainers can change the version label to modify the version bump.
  • If the bot has failed to detect any changes, or if this pull request needs to update multiple packages to different versions or requires a more comprehensive changelog entry, maintainers can update the changelog file directly.

@freddyaboulton freddyaboulton marked this pull request as ready for review March 18, 2025 18:28
@freddyaboulton freddyaboulton requested review from aliabid94, abidlabs, pngwn, aliabd, dawoodkhan82 and hannahblair and removed request for abidlabs March 18, 2025 18:28
@dawoodkhan82
Copy link
Collaborator

dawoodkhan82 commented Mar 18, 2025

@freddyaboulton What are your thoughts on adding the "share" button to the footer in a little dropdown? Something like this? Only downside is it would be kinda tucked away.

Untitled-2025-02-20-0129

@freddyaboulton
Copy link
Collaborator Author

I felt that a button would maximize visibility. But open to adding it to the share menu in addition once that's in

@dawoodkhan82
Copy link
Collaborator

@freddyaboulton Makes sense!

@abidlabs
Copy link
Member

abidlabs commented Mar 19, 2025

Sweet @freddyaboulton! Testing it right now, a few suggestions in the meantime:

  • Is it possible to color the SVG of the chain as the same color as the button as the text on the button? Not sure if this actually possible but it would be nicer stylstically. For example, here's how it currently looks in light mode, default theme:
image
  • Can we add gr.DeepLinkButton to a few of our demos to help showcase its usage?

  • Can we add it to our guides, perhaps here: https://www.gradio.app/guides/sharing-your-app?

  • Finally, can we add a parameter to gr.Interface that adds it to your Interface and make it the default in Spaces?

@abidlabs
Copy link
Member

abidlabs commented Mar 19, 2025

One issue I noticed while testing was that it does not seem to work in reload mode? For repro, my app.py file was:

import gradio as gr

def welcome(name):
    return f"Welcome to Gradio, {name}!"

with gr.Blocks() as demo:
    gr.Markdown(
    """
    # Hello World!
    Start typing below to see the output.
    """)
    inp = gr.Textbox(placeholder="What is your name?")
    out = gr.Textbox()
    inp.change(welcome, inp, out)
    gr.DeepLinkButton()

if __name__ == "__main__":
    demo.launch()

and when I ran gradio app.py and clicked the button, I got the link: http://127.0.0.1:7863/?deep_link=nopWu6Oo-BI. But pasting it to a new browser does not restore the state of the components.

@abidlabs
Copy link
Member

abidlabs commented Mar 19, 2025

Otherwise works great in a variety of demos that I tested with & the UX is fantastic. Great work @freddyaboulton!

@abidlabs
Copy link
Member

Oh one more thing, I tested on Spaces: https://abidlabs-chatbot-streaming-test.hf.space/ and while the generated link technically works: https://abidlabs-chatbot-streaming-test.hf.space/?__theme=system&deep_link=98QjNSX0-NI, it uses the embedded app url instead of the Space URL. I think it would be nicer if it could use the Space URL if on Spaces, since that also works: https://huggingface.co/spaces/abidlabs/chatbot_streaming_test?deep_link=98QjNSX0-NI

@abidlabs
Copy link
Member

Oh one more thing, I tested on Spaces: https://abidlabs-chatbot-streaming-test.hf.space/ and while the generated link technically works: https://abidlabs-chatbot-streaming-test.hf.space/?__theme=system&deep_link=98QjNSX0-NI, it uses the embedded app url instead of the Space URL. I think it would be nicer if it could use the Space URL if on Spaces, since that also works: https://huggingface.co/spaces/abidlabs/chatbot_streaming_test?deep_link=98QjNSX0-NI

Actually ignore this, the way you have it right now is better in case there are multiple Space replicas. In that case, the state of the app will be serialized to a specific replica, which will be identifiable by the root URL

@freddyaboulton
Copy link
Collaborator Author

Sounds good @abidlabs ! Thanks

abidlabs and others added 11 commits March 20, 2025 12:40
* changes

* add changeset

* type

* add changeset

---------

Co-authored-by: gradio-pr-bot <[email protected]>
…xt (#10814)

* changes

* add changeset

* format'

* test

* copy

* changes

* doc

* format

---------

Co-authored-by: gradio-pr-bot <[email protected]>
* changes

* add changeset

---------

Co-authored-by: Ali Abid <[email protected]>
Co-authored-by: gradio-pr-bot <[email protected]>
* remove editable condition

* - add test
- improve html semantics

* add changeset

* fix test

* fix test

* - fix test
- fix column widths changing on sort

* swap e2e for story

---------

Co-authored-by: gradio-pr-bot <[email protected]>
* changes

* changes

* add changeset

* changes

* changes

* changes

* changes

* changes

* changes

* changes

---------

Co-authored-by: Ali Abid <[email protected]>
Co-authored-by: gradio-pr-bot <[email protected]>
Co-authored-by: Abubakar Abid <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@freddyaboulton
Copy link
Collaborator Author

hi @abidlabs ! thanks for the thoughtful review.

Making the svg color change in response to the theme.

Not currently possible with how svgs are embedded in buttons via the python class. The right way to do this would be to have the svg color match the button-primary-text-color css variable but those are not defined when the backend runs.

Deep links don't work in reload mode

Fixed

Including in sharing your app guide

Done!

Adding to demos

I started doing this but then I realized that the demos on the website run on gradio-lite so the button wouldn't actually work. Let's leave gradio-lite compatibility for a separate PR if we really want to support it.

Automatically add a deep link button for interfaces on spaces

Done!

@@ -53,6 +54,18 @@ After you have [created a free Hugging Face account](https://huggingface.co/join
<source src="https://github.com/gradio-app/gradio/blob/main/guides/assets/hf_demo.mp4?raw=true" type="video/mp4" />
</video>

## Sharing Deep Links

You can add a button to your Gradio app that creates a unique URL you can use to share your app **as it currently is** with others. This is useful for sharing unique and interesting generations from your application , or for saving a snapshot of your app at a particular point in time.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can add a button to your Gradio app that creates a unique URL you can use to share your app **as it currently is** with others. This is useful for sharing unique and interesting generations from your application , or for saving a snapshot of your app at a particular point in time.
You can add a button to your Gradio app that creates a unique URL you can use to share your app and all components **as they currently are** with others. This is useful for sharing interesting generations from your application or for saving a snapshot of your app at a particular point in time.

Comment on lines +66 to +67
$code_deep_link
$demo_deep_link
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this demo was pushed (which might also be why the CI is failing)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea good call!

@@ -144,6 +145,7 @@ def __init__(
| None = None,
time_limit: int | None = 30,
stream_every: float = 0.5,
deep_link: str | DeepLinkButton | None = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add docstring for this param

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, as it's currently implemented, there's no way for users to disable the deep link for their Gradio app on Spaces. I think we should allow this, for example if a user sets deep_link=False

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if I want to "just enable it" in my Interface running locally, I should be able to set deep_link=True without having to provide a str

Copy link
Member

@abidlabs abidlabs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM great PR @freddyaboulton!

I noticed one other issue, which is that if you launch a Gradio app and click on the deep link button before any other events, then you get an invalid deep link (e.g. http://127.0.0.1:7865/?deep_link=Error). We should handle this case. But otherwise, all of the issues I identified are resolved!

@freddyaboulton freddyaboulton merged commit c05610c into main Mar 21, 2025
22 of 23 checks passed
@freddyaboulton freddyaboulton deleted the load-state-from-url branch March 21, 2025 18:15
@freddyaboulton
Copy link
Collaborator Author

Thank you for the review @abidlabs!

@aliabid94
Copy link
Collaborator

Very cool @freddyaboulton! Feel like we should replace the flag button with the deep link button on Interfaces on Spaces

@abidlabs
Copy link
Member

That’s exactly what happens @aliabid94 (flagging is disabled, share links are enabled on Spaces)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow users to share app + settings via a URL
7 participants